package com.koron.order.LineHomepage.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.koron.bean.base.Response;
import com.koron.bean.system.org.OrgBean;
import com.koron.common.core.business.configsettings.utils.ConfigInfoTool;
import com.koron.common.core.business.system.SystemCacheUtil;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.StringUtils;
import com.koron.order.LineHomepage.bean.VO.*;
import com.koron.order.LineHomepage.bean.dto.LineEquipmentDTO;
import com.koron.order.LineHomepage.bean.dto.LineKeyRiskDTO;
import com.koron.order.LineHomepage.bean.dto.LineRiskDTO;
import com.koron.order.LineHomepage.bean.query.DefectReportQuery;
import com.koron.order.LineHomepage.bean.query.LineEquipmentQuery;
import com.koron.order.LineHomepage.bean.query.RiskReportQuery;
import com.koron.order.LineHomepage.mapper.LineHomePageMapper;
import com.koron.order.LineHomepage.service.LineHomePageService;
import com.koron.order.linedefect.base.bean.po.DefectBean;
import com.koron.order.linedefect.base.bean.query.DefectQuery;
import com.koron.order.linedefect.base.service.DefectService;
import com.koron.order.linepatrol.base.bean.po.PatrolPointPo;
import com.koron.order.linepatrol.base.bean.vo.PatrolDetailsVO;
import com.koron.order.linepatrol.base.business.service.PatrolBusinessService;
import com.koron.order.linepatrol.base.mapper.PatrolPointMapper;
import com.koron.order.linepatrol.base.service.PatrolEquipmentService;
import com.koron.order.linepatrol.base.service.PatrolPointService;
import com.koron.order.overhaul.bean.dto.Equipment;
import com.koron.order.risk.base.bean.query.LineKeyRiskQuery;
import com.koron.order.risk.base.bean.query.LineRiskQuery;
import com.koron.order.risk.base.bean.vo.LineKeyRiskVO;
import com.koron.order.risk.base.bean.vo.LineRiskVO;
import com.koron.order.risk.base.mapper.LineEquipmentMapper;
import com.koron.order.risk.base.service.LineRiskService;
import com.koron.order.risk.feign.LineEquipmentFeign;
import com.koron.order.risk.feign.dto.EquipmentParams;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName: HomePageServiceImpl
 * @Description:
 * @Date: 2023/2/15
 * @Author: 李一辰
 * @Version: 1.0
 **/
@Service
public class LineHomePageServiceImpl implements LineHomePageService {

    @Autowired
    private LineEquipmentFeign equipmentFeign;
    @Autowired
    LineRiskService lineRiskService;

    @Autowired
    DefectService defectService;

    @Autowired
    PatrolPointService patrolPointService;


    @Autowired
    PatrolBusinessService linePatrolBusinessService;

    @Autowired
    PatrolEquipmentService linePatrolEquipmentService;

    private String getCurrDs() {
        return ThreadLocalContext.get().getCurrDs();
    }

    @Override
    @TaskAnnotation("getDefectCount")
    public List<LineDefectVO> getDefectCount(SessionFactory sessionFactory) {
        LineHomePageMapper mapper = sessionFactory.getMapper(LineHomePageMapper.class);
        return mapper.getDefectCount();
    }

    @Override
    public Integer getLineRiskCount(SessionFactory sessionFactory) {
        LineHomePageMapper mapper = sessionFactory.getMapper(LineHomePageMapper.class);
        return mapper.getRiskCount();
    }

    @Override
    public Integer getUnvRiskCount(SessionFactory sessionFactory) {
        LineHomePageMapper mapper = sessionFactory.getMapper(LineHomePageMapper.class);
        return mapper.getUnvRiskCount();
    }

    @TaskAnnotation("getRiskCount")
    public Integer getRiskCount(SessionFactory sessionFactory) {
        return getLineRiskCount(sessionFactory) + getUnvRiskCount(sessionFactory);
    }

    @Override
    @TaskAnnotation("getLineTripAnnual")
    public AnnualTripVO getLineTripAnnual(SessionFactory sessionFactory) {
        LineHomePageMapper mapper = sessionFactory.getMapper(LineHomePageMapper.class);
        AnnualTripVO annualTripVO = new AnnualTripVO();
        Integer thisYearTrip = mapper.getThisYearTrip();
        Integer lastYearTrip = mapper.getLastYearTrip();
        annualTripVO.setThisCount(thisYearTrip);
        annualTripVO.setLastCount(lastYearTrip);
        if (lastYearTrip == 0) {
            annualTripVO.setPercentage("0%");
            return annualTripVO;
        }
        BigDecimal thisYear = new BigDecimal(thisYearTrip);
        BigDecimal lastYear = new BigDecimal(lastYearTrip);

        BigDecimal divide = thisYear.divide(lastYear, 2, RoundingMode.HALF_UP);
        double value = divide.doubleValue();
        if (value > 1) {
            annualTripVO.setFlag("该年度上升");
            annualTripVO.setPercentage((value * 100 - 100) + "%");
        } else if (value < 1) {
            annualTripVO.setFlag("该年度下降");
            annualTripVO.setPercentage((100 - value * 100) + "%");
        } else {
            annualTripVO.setFlag("该年度持平");
            annualTripVO.setPercentage((100 - value * 100) + "%");
        }
        return annualTripVO;
    }

    @Override
    @TaskAnnotation("getLineTripQuarter")
    public AnnualTripVO getLineTripQuarter(SessionFactory sessionFactory) {
        LineHomePageMapper mapper = sessionFactory.getMapper(LineHomePageMapper.class);
        AnnualTripVO annualTripVO = new AnnualTripVO();
        annualTripVO.setThisCount(mapper.getThisQuarterTrip());
        annualTripVO.setLastCount(mapper.getLastQuarterTrip());
        if (annualTripVO.getLastCount() == 0) {
            annualTripVO.setPercentage("0%");
            return annualTripVO;
        }
        BigDecimal thisYear = new BigDecimal(annualTripVO.getThisCount());
        BigDecimal lastYear = new BigDecimal(annualTripVO.getLastCount());
        BigDecimal divide = thisYear.divide(lastYear, 2, RoundingMode.HALF_UP);
        double value = divide.doubleValue();
        if (value > 1) {
            annualTripVO.setFlag("该季度上升");
            annualTripVO.setPercentage((value * 100 - 100) + "%");
        } else if (value < 1) {
            annualTripVO.setFlag("该季度下降");
            annualTripVO.setPercentage((100 - value * 100) + "%");
        } else {
            annualTripVO.setFlag("该季度持平");
            annualTripVO.setPercentage((100 - value * 100) + "%");
        }
        return annualTripVO;
    }
    //统计风险上报类比
    @Override
    @TaskAnnotation("getRiskReportingAnalogy")
    public List<RiskReportVO> getRiskReportingAnalogy(SessionFactory sessionFactory, RiskReportQuery riskReportQuery) {
        LineHomePageMapper mapper = sessionFactory.getMapper(LineHomePageMapper.class);
        List<String> deptList = mapper.getDeptAndOrg(riskReportQuery.getId());
        riskReportQuery.setDeptIds(deptList);
        riskReportQuery.setDate(new Date(riskReportQuery.getDate().getTime()));
        List<RiskReportVO> riskKeyword = mapper.getRiskKeyword(riskReportQuery);
        Integer total = 0;
        for (RiskReportVO riskReportVO : riskKeyword) {
            total += riskReportVO.getCount();
        }
        BigDecimal totalDecimal = new BigDecimal(total);
        for (RiskReportVO riskReportVO : riskKeyword) {
            Integer count = riskReportVO.getCount();
            BigDecimal countDecimal = new BigDecimal(count * 100);
            BigDecimal divide = countDecimal.divide(totalDecimal, 2, RoundingMode.HALF_UP);
            riskReportVO.setPercentage(divide + "%");
        }
        return riskKeyword;
    }
    //统计缺陷关键字上报类比
    @Override
    @TaskAnnotation("getDefectKeys")
    public List<DefectReportVO> getDefectKeys(SessionFactory sessionFactory, DefectReportQuery defectReportQuery) {
        LineHomePageMapper mapper = sessionFactory.getMapper(LineHomePageMapper.class);
        List<String> deptList = mapper.getDeptAndOrg(defectReportQuery.getId());
        defectReportQuery.setDeptIds(deptList);
        defectReportQuery.setDate(new Date(defectReportQuery.getDate().getTime()));
        List<DefectReportVO> defectKeys = mapper.getDefectKeys(defectReportQuery);
        Integer total = 0;
        for (DefectReportVO defectReportVO : defectKeys) {
            total += defectReportVO.getCount();
        }
        BigDecimal totalDecimal = new BigDecimal(total);
        for (DefectReportVO defectReportVO : defectKeys) {
            Integer count = defectReportVO.getCount();
            BigDecimal countDecimal = new BigDecimal(count * 100);
            BigDecimal divide = countDecimal.divide(totalDecimal, 2, RoundingMode.HALF_UP);
            defectReportVO.setPercentage(divide + "%");
        }
        return defectKeys;
    }
    //缺陷统计，统计部门未归档的缺陷数，并按照缺陷等级展示，记录是否已完成，及时完成，以及未完成等
    @Override
    @TaskAnnotation("getDefectStatistic")
    public DefectStatistic getDefectStatistic(SessionFactory sessionFactory, Date date) {
        LineHomePageMapper mapper = sessionFactory.getMapper(LineHomePageMapper.class);
        //拿到部门下所有的组织，将其统一归纳在所选部门下
        List<LineDeptAndOrg> deptAndOrg2 = mapper.getDeptAndOrg2();
        List<String> orgIds = deptAndOrg2.stream().map(LineDeptAndOrg::getId).distinct().collect(Collectors.toList());
        Set<String> deptIds = deptAndOrg2.stream().map(LineDeptAndOrg::getParentId).collect(Collectors.toSet());
        deptIds.addAll(orgIds);
        List<DefectStatisticVO> defectStatistic = mapper.getDefectStatistic(date, deptIds);
        for (DefectStatisticVO defectStatisticVO : defectStatistic) {
            String deptManage = defectStatisticVO.getDeptManage();
            OrgBean orgBean = SystemCacheUtil.queryDeptByOrgId(deptManage);
            assert orgBean != null;
            if (orgBean.getLevelPath().equals("2")) {
                continue;
            } else {
                defectStatisticVO.setDeptManageName(orgBean.getName());
                defectStatisticVO.setDeptManage(orgBean.getDeptId());
            }
        }
        Long total = defectStatistic.stream().filter(i -> !i.getStatus().equals("ARCHIVED")).count();
        Set<String> deptManageList = defectStatistic.stream().map(DefectStatisticVO::getDeptManageName).collect(Collectors.toSet());
        Map<String, List<DefectStatisticVO>> map = defectStatistic.stream().collect(Collectors.groupingBy(DefectStatisticVO::getDeptManageName));
        ArrayList<DefectStatisticVO> list = new ArrayList<>();
        for (String manageName : deptManageList) {
            List<DefectStatisticVO> defectStatisticVOS = map.get(manageName);
            DefectStatisticVO defectStatisticVO = new DefectStatisticVO();
            Long urgentLine = defectStatisticVOS.stream().filter(i -> i.getLevel().equals("urgent_line")).count();
            Long commonlyLine = defectStatisticVOS.stream().filter(i -> i.getLevel().equals("commonly_line")).count();
            Long majorLine = defectStatisticVOS.stream().filter(i -> i.getLevel().equals("major_line")).count();
            int isFinish = defectStatisticVOS.stream().mapToInt(DefectStatisticVO::getIsFinish).sum();
            int isFinishOnTime = defectStatisticVOS.stream().mapToInt(DefectStatisticVO::getIsFinishOnTime).sum();
            int notFinish = defectStatisticVOS.stream().mapToInt(DefectStatisticVO::getNotFinish).sum();
            Long count = urgentLine + commonlyLine + majorLine;
            defectStatisticVO.setUrgent_line(urgentLine.intValue());
            defectStatisticVO.setCommonly_line(commonlyLine.intValue());
            defectStatisticVO.setMajor_line(majorLine.intValue());
            defectStatisticVO.setNotFinish(notFinish);
            defectStatisticVO.setIsFinish(isFinish);
            defectStatisticVO.setIsFinishOnTime(isFinishOnTime);
            defectStatisticVO.setDeptManageName(manageName);
            BigDecimal OnTimeFinishDecimal = new BigDecimal(isFinishOnTime * 100);
            BigDecimal totalDecimal = new BigDecimal(count);
            BigDecimal value = OnTimeFinishDecimal.divide(totalDecimal, 2, RoundingMode.HALF_UP);
            defectStatisticVO.setDefectRemoval(value + "%");
            list.add(defectStatisticVO);
        }
        return new DefectStatistic(total.intValue(), list);
    }

    @Override
    @TaskAnnotation("list")
    public List<Equipment> list(SessionFactory sessionFactory, LineEquipmentQuery query) {
        // 1. 查询根设备
        Map<String, String> config = ConfigInfoTool.getConfigByCode("equipment", "line_root_device");
        String id = config.get("id");
        sessionFactory.setDbEnv(getCurrDs());
        LineEquipmentMapper mapper = sessionFactory.getMapper(LineEquipmentMapper.class);
        Equipment root = mapper.getById(id);
        List<Equipment> towerEquipmentList = mapper.selectSimpleTowerEquipment(root.getLevelPath(), query);
        List<String> ids = towerEquipmentList.stream().map(Equipment::getId).collect(Collectors.toList());
        List<String> names = towerEquipmentList.stream().map(Equipment::getName).collect(Collectors.toList());
        Response<List<EquipmentParams>> batchBaseParams = equipmentFeign.getBatchBaseParams(ids);
        List<EquipmentLatlon> latlons = new ArrayList<>();
        if(names.size() >0){
            LineHomePageMapper mapper1 = sessionFactory.getMapper(LineHomePageMapper.class);
            latlons = mapper1.selectLatLong(names);
        }
        Map<String, String> map = latlons.stream().collect(Collectors.toMap(EquipmentLatlon::getName, EquipmentLatlon::getLatlon, (e1, e2) -> e1));
        if(CollUtil.isEmpty(batchBaseParams.getData())){
            return towerEquipmentList;
        }
        List<EquipmentParams> data = batchBaseParams.getData();
        Map<String, EquipmentParams> deptMap = data.stream()
                .filter(e -> "管理部门".equals(e.getParamName()))
                .collect(Collectors.toMap(EquipmentParams::getEquipmentId, e -> e, (o1, o2) -> o1));
        for (Equipment equipment : towerEquipmentList) {
            String latlon = map.get(equipment.getName());
            if(StringUtils.isNotEmpty(latlon)){
                String[] split = latlon.split(",");
                equipment.setLatitude(split[1]);
                equipment.setLongitude(split[0]);
            }
            EquipmentParams params = deptMap.get(equipment.getId());
            if (StringUtils.isNull(params)) {
                continue;
            }
            equipment.setDeptId(params.getParamResult());
            equipment.setDeptName(params.getParamValue());
        }
        return towerEquipmentList;
    }

    @Override
    @TaskAnnotation("selectEquipmentDetail")
    public LineEquipmentDTO selectEquipmentDetail(SessionFactory sessionFactory,String id) {
        if(StringUtils.isEmpty(id)){
            return new LineEquipmentDTO();
        }
        LineEquipmentDTO lineEquipmentDTO = new LineEquipmentDTO();
        LineEquipmentMapper mapper = sessionFactory.getMapper(LineEquipmentMapper.class);
        //1.根据杆塔id查询杆塔基础数据信息
        Equipment equipment = mapper.getById(id);
        lineEquipmentDTO.setEquipment(equipment);
        //2.根据杆塔id查询未消缺的缺陷
        DefectQuery defectQuery = new DefectQuery();
        defectQuery.setEquipmentId(equipment.getId());
        List<DefectBean> defectBeans = defectService.queryList(sessionFactory, defectQuery);
        List<DefectBean> defects = defectBeans.stream().filter(i -> !"DRAFT".equals(i.getStatus())).filter(i->!"ARCHIVED".equals(i.getStatus())).collect(Collectors.toList());
        lineEquipmentDTO.setDefects(defects);
        //3.根据杆塔id查询未消缺的风险
        LineRiskQuery lineRiskQuery = new LineRiskQuery();
        //风险管控单保存的是线路id，我们需要先靠线路id去查询，再获得风险管控但下保存的塔段集合，最后拿杆塔id与之匹配
        List<LineRiskVO> list = new ArrayList<>();
        if(StringUtils.isNotEmpty(equipment.getParentId())){
            lineRiskQuery.setEquipmentId(equipment.getParentId());
           list = lineRiskService.list(sessionFactory, lineRiskQuery);
        }
       //风险管控单列表不为空则进行过滤并setter
        if(CollectionUtil.isNotEmpty(list)){
           List<LineRiskVO> risks = list.stream().filter(i->CollectionUtil.isNotEmpty(i.getLineRiskPartList())).filter(i ->
                    i.getLineRiskPartList().stream()
                   .filter(j->StringUtils.isNotEmpty(j.getEquipmentId()))
                   .anyMatch(j -> equipment.getId().equals(j.getEquipmentId())))
                   .filter(i -> !"DRAFT".equals(i.getStatus()) && !"ARCHIVED".equals(i.getStatus()))
                   .collect(Collectors.toList());
           lineEquipmentDTO.setRisks(risks);
       }else{
            lineEquipmentDTO.setRisks(list);
        }

        //4.查询巡视记录
        PatrolPointPo patrolPointPo = new PatrolPointPo();
        patrolPointPo.setPlanPatrolPointId(equipment.getId());
        PatrolPointMapper mapper1 = sessionFactory.getMapper(PatrolPointMapper.class);
        List<PatrolDetailsVO> patrolDetailsVOS = mapper1.selectList(equipment.getId());
        lineEquipmentDTO.setPatrolPointPos(patrolDetailsVOS);
        return lineEquipmentDTO;
    }
    @Override
    @TaskAnnotation("listRisks")
    public List<LineRiskVO> listRisks(SessionFactory sessionFactory, LineRiskQuery lineRiskQuery){
        return lineRiskService.list(sessionFactory, lineRiskQuery);
    }
    @Override
    @TaskAnnotation("selectRiskDetail")
    public LineRiskDTO selectRiskDetail(SessionFactory sessionFactory, String id) {
        if(StringUtils.isEmpty(id)){
            return  new LineRiskDTO();
        }
        LineRiskVO lineRiskVO = lineRiskService.getById(sessionFactory, id);
        PatrolPointMapper mapper = sessionFactory.getMapper(PatrolPointMapper.class);
        List<PatrolDetailsVO> patrolDetailsVOS = mapper.selectList(lineRiskVO.getId());
        LineRiskDTO lineRiskDTO = new LineRiskDTO();
        lineRiskDTO.setLineRiskVO(lineRiskVO);
        lineRiskDTO.setPatrolPointPos(patrolDetailsVOS);
        return lineRiskDTO;
    }
    @Override
    @TaskAnnotation("listKeyRisks")
    public List<LineKeyRiskVO> listKeyRisks(SessionFactory sessionFactory, LineKeyRiskQuery lineRiskQuery){
        return lineRiskService.listAndKeyLevel(sessionFactory, lineRiskQuery);
    }

    @Override
    @TaskAnnotation("selectKeyRisks")
    public LineKeyRiskDTO selectKeyRisks(SessionFactory sessionFactory,  String id) {
        if(StringUtils.isEmpty(id)){
            return  new LineKeyRiskDTO();
        }
        LineKeyRiskVO keyRiskVO = lineRiskService.getByIdAndKeyLevel(sessionFactory, id);
        PatrolPointMapper mapper = sessionFactory.getMapper(PatrolPointMapper.class);
        List<PatrolDetailsVO> patrolDetailsVOS = mapper.selectList(keyRiskVO.getId());
        LineKeyRiskDTO lineRiskDTO = new LineKeyRiskDTO();
        lineRiskDTO.setLineKeyRiskVO(keyRiskVO);
        lineRiskDTO.setPatrolPointPos(patrolDetailsVOS);
        return lineRiskDTO;
    }
}
